package com.gln.bloger.dao.impl;

import java.util.Hashtable;
import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Expression;
import org.hibernate.criterion.Restrictions;

import com.gln.bloger.dao.UserDao;
import com.gln.bloger.exception.BlogerException;
import com.gln.bloger.exception.BusinessException;
import com.gln.bloger.exception.DBOperateException;
import com.gln.bloger.log.Logging;
import com.gln.bloger.pojos.User;

public  class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {
	
    /**
     * cached mapping of mail address -> userIds
     */
    private Hashtable<String ,String> mailAddressToIdMap = 
    	                                       new Hashtable<String ,String>();
	
    /**
	 * get user by name optionally including disable users
	 */
    @SuppressWarnings("unchecked")
	public User getByMail(String mail) throws BlogerException{
		/* name is null*/
    	if(null == mail){
    		Logging.debug("can not get user with a null mail");
    		throw new BusinessException("mail.null");
    	}
    	
    	/**
    	 * contained in cached map,get the id by name
    	 */
		if(mailAddressToIdMap.containsKey(mail)){
			/*get userInfo*/
			User user = this.get((String)(mailAddressToIdMap.get(mail)));
			
			if(user != null){
				Logging.debug("get user by mail :"+mail);
				return user;
				//the cached information must be old,remove it
			}else{
				this.mailAddressToIdMap.remove(mail);
			}
		}
		
		/*cache failed, do lookup by user mail from database*/
		try {
			User user  = null;
			DetachedCriteria criteria = DetachedCriteria.forClass(User.class);
            criteria.add(Restrictions.eq("email", mail));
            List<User> users = getHibernateTemplate().findByCriteria(criteria);
            if(null != users && users.size() > 0){
            	user = users.get(0);
            }
            // add mapping to cache
            if(user != null) {
            	Logging.debug("userNameToIdMap CACHE MISS - "+mail);
            	this.mailAddressToIdMap.put(user.getEmail(), user.getId());
            }
            return user;
        } catch (HibernateException e) {
        	throw new DBOperateException(e.getMessage());
        }
	}

	/**
	 * get all user optionally including disable users
	 */
	@SuppressWarnings("unchecked")
	public List <User>getUsers(Boolean enable) throws BlogerException{
		List<User> users = null;
		try {
			Session session = getSession();

			Criteria criteria = session.createCriteria(User.class);
			/**
			 * add the expression
			 */
			criteria.add(Expression.conjunction().add(Expression.eq("enabled", enable)));
			users = criteria.list();
		}catch(HibernateException e){
			throw new BlogerException(e.getMessage());
		}
        return users;
	}

	public List<User> getUsers() throws BlogerException {
		// TODO Auto-generated method stub
		return null;
	}
}
